package com.xx.happychatboot.middleware.netty.service.impl;

import cn.hutool.json.JSONUtil;
import com.xx.happychatboot.base.utils.RedisUtils;
import com.xx.happychatboot.middleware.netty.channel.WebSocketChannelMap;
import com.xx.happychatboot.middleware.netty.constants.WebSocketConstants;
import com.xx.happychatboot.middleware.netty.constants.WebSocketRedisConstants;
import com.xx.happychatboot.middleware.netty.domain.enums.WebSocketCallBackEnums;
import com.xx.happychatboot.middleware.netty.domain.vo.response.WebSocketResponse;
import com.xx.happychatboot.middleware.rocketmq.factory.rocketmq.RocketMqFactory;
import com.xx.happychatboot.middleware.netty.service.WebSocketService;
import com.xx.happychatboot.middleware.rocketmq.strategy.rocketmq.AbstractRocketMqStrategy;
import com.xx.happychatboot.middleware.rocketmq.domain.dto.RocketMqCommonDto;
import com.xx.happychatboot.serve.user.domain.entity.SysUser;
import com.xx.happychatboot.serve.user.service.ISysUserService;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class WebSocketServiceImpl implements WebSocketService {

    @Autowired
    private ISysUserService sysUserService;

    @Override
    public void saveConnect(Channel channel, String username) {
        // 获取当前用户信息
        SysUser sysUser = sysUserService.loadUserByUsername(username);
        if (Objects.isNull(sysUser)) {
            throw new RuntimeException("用户不存在");
        }
        // 将Channel和用户名绑定
        log.info("用户{}上线", sysUser.getUsername());
        WebSocketChannelMap.addChannelCtx(sysUser.getUserId(), channel);

        // 设置用户id属性
        AttributeKey<Long> userIdAttr = AttributeKey.valueOf(WebSocketConstants.USER_ID);
        channel.attr(userIdAttr).set(sysUser.getUserId());

        // 初始化心跳次数
        AttributeKey<Long> heartBeatAttr = AttributeKey.valueOf(WebSocketConstants.HEARTBEAT_TIMES);
        channel.attr(heartBeatAttr).set(0L);

        // 将uid和channel_id 存储到redis中
        String key = WebSocketRedisConstants.WEB_SOCKET_USER_SERVER_ID + sysUser.getUserId();
        RedisUtils.set(key, channel.id().asLongText(), WebSocketRedisConstants.ONLINE_TIMEOUT_SECOND, TimeUnit.SECONDS);

        WebSocketResponse webSocketResponse = WebSocketResponse.callBackType(WebSocketCallBackEnums.LOGIN_CALL_BACK.getType());
        // 响应webSocket
        sendMsg(channel, webSocketResponse);
    }

    /**
     * 给本地channel发送消息
     *
     * @param channel
     * @param webSocketResponse
     */
    @Override
    public void sendMsg(Channel channel, WebSocketResponse<?> webSocketResponse) {
        channel.writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(webSocketResponse)));
    }

    /**
     * 执行对应rocketmq操作
     *
     * @param rocketMqCommonDto
     */
    @Override
    public void rocketMqExecute(RocketMqCommonDto rocketMqCommonDto) {
        if (Objects.isNull(rocketMqCommonDto)
                || Objects.isNull(rocketMqCommonDto.getUid())) {
            return;
        }

        // 通过uid获取channel
        Channel channel = WebSocketChannelMap.getChannel(rocketMqCommonDto.getUid());

        if (Objects.isNull(channel)) {
            return;
        }

        // 获取对应的策略
        AbstractRocketMqStrategy strategy = RocketMqFactory.getStrategyNoNull(rocketMqCommonDto.getCode());

        if (Objects.isNull(strategy)) {
            return;
        }

        // 处理前端发送过来的消息
        strategy.execute(channel, rocketMqCommonDto);
    }

}
